home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Trading on the Edge
/
Trading On The Edge - CD-ROM Toolkit (Wayzata Technology)(2031)(1994).bin
/
pc
/
mac_file
/
vendor_d
/
neuralwa
/
nw2v50
/
weathrio.c
< prev
next >
Wrap
Text File
|
1993-08-23
|
23KB
|
761 lines
/* 17:00 04-Jul-88 (weathrio.c) Weather Prediction with Madeline */
/************************************************************************
* Copyright(C) 1987-1992 NeuralWare Inc *
* Penn Center West, IV-227, Pittsburgh, PA 15276 *
* Telephone: (412) 787-8222 FAX: (412) 787-8220 *
* *
* All rights reserved. No part of this program may be reproduced, *
* stored in a retrieval system, or transmitted, in any form or by any *
* means, electronic, mechanical, photocopying, recording or otherwise *
* without the prior written permission of the copyright owner, *
* NeuralWare, Inc. *
* *
* PROPRIETARY NOTICE *
* *
* This document is the property of NeuralWare, Inc. and contains *
* trade-secrets and other proprietary information. The information *
* herein is reserved as proprietary to NeuralWare, and is not to be *
* published, reproduced, copied, disclosed, used, or reverse *
* engineered without the express written consent of a duly authorized *
* representative of NeuralWare. *
************************************************************************
*/
#include "userutl.h"
#include <string.h>
#include <math.h>
#ifndef SUN
#ifndef DLC
#include <stdlib.h>
#endif
#endif
#ifdef MAC
#include "macuio.redef"
#endif
#if defined(_MSC_VER) || defined(__TURBOC__)
int strcmpl( char *, char * );
#endif
/************************************************************************
*
* WEATHRIO - Weather Prediction User I/O
*
************************************************************************
*/
/* external routines */
#ifdef PROTOTYPING
/* --- prototypes --- */
double fabs( double );
double sqrt( double );
#else
double fabs( );
double sqrt( );
#endif
static short nw_type; /* type of network : */
#define ADALINE 0
#define OTHER 1
/* local data declarations */
static float bp, dbp; /* bar. pressure, delta b.p. */
static float prec_tod, prec_tom, prec_nxt; /* rainfall today, tomorrow..*/
static int wd, dwd; /* wind direction, delta w. dir */
static char date[12];
/* File definitions and declarations */
#define MAX_STR 132 /* For reading from file */
static char fbuf[3][MAX_STR + 1]; /* buffers for file i/o */
static int tod_buff, tom_buff, nxt_buff; /* buffer indices */
static int num_readings; /* Actual # readings */
static short no_more_data; /* recall flag */
static FILE *fp = 0;
static FILE *ifp = 0;
static long start_pos;
static char file_name[40]; /* larger for SUNs */
/* Forecast parameters from user' file */
static float prec_thr; /* precipitation threshold */
static float bp_low, bp_high; /* barometric pressure limits */
static float dbp_low, dbp_high; /* delta barometric pressure limits */
static float wd_low, wd_high; /* wind direction limits */
static float dwd_low, dwd_high; /* delta wind direction limits */
/* Following need to be long for MAC scanfs */
static long bp_npe; /* # PEs for barometrics pressure */
static long dbp_npe; /* # PEs for delta bar. pressure */
static long wd_npe; /* # PEs for wind direction */
static long dwd_npe; /* # PEs for delta wind direction */
/* Network parameters */
static int nlayp, ninp, noutp, ltype; /* Network parameters */
static char *csp, *netnp; /* Network pointers*/
/* graphics parameters */
static int xsize, ysize, ncolor, chrx, chry;
/* Output display definitions and declarations for learning */
static double tod_mse, tom_mse, nxt_mse; /* Mean square errors */
/* Output display definitions and declarations for recall */
#define NUM_DISP 31 /* Maximum number displayed*/
#define X_MARGIN 5
#define Y_MARGIN 5
static int rstrtx, rstrty, rendx, rendy; /* Display window params */
static int ract_y, rtod_y, rtom_y, rnxt_y;/* y values for the 3 rows */
static int rdata; /* start of data display */
static int curr_pos; /* current data position */
static int dateline, actline;
/* Results */
static float tod_correct, tom_correct, nxt_correct;
#ifndef DLC
/* special routine to fill in for SUN386i */
int strcmpl( pa, pb )
char *pa, *pb; /* strings to compare */
{
int a, b; /* work characters */
int rc; /* return code */
for(;;) {
a = *pa++;
b = *pb++;
if ( 'A' <= a && a <= 'Z' ) a -= 'A'-'a';
if ( 'A' <= b && b <= 'Z' ) b -= 'A'-'a';
if ( (rc = a - b) != 0 ) return( rc );
if ( a == 0 ) return( 0 );
}
}
#endif
/* local routines */
/* --- prototypes --- */
void encode ARGLIST(( char * ));
void decode ARGLIST(( void ));
void li_code ARGLIST(( double, double, double, int, char * ));
void disp_rwdw ARGLIST (( void ));
void disp_forecast ARGLIST (( void ));
void encode( buf )
char *buf;
{
char sbuf[100];
float denom, wf;
float nbp, ndbp, nwd, ndwd; /* Normalized data */
if ( nw_type == ADALINE ) {
strcpy( buf, date );
strcat( buf, " " );
li_code( bp, bp_low, bp_high, (int)bp_npe, sbuf );
strcat( buf, sbuf );
strcat( buf, " " );
wf = (float) fabs( (double)dbp_low );
if ( wf < dbp_high ) wf = dbp_high;
li_code( (double) fabs((double)dbp), 0.0, wf, (int)(dbp_npe-1), sbuf );
strcat( buf, sbuf );
strcat( buf, " " );
if ( dbp < 0.0 ) strcat( buf, "0 " );
else strcat( buf, "1 " );
li_code( (double) wd, wd_low, wd_high, (int)wd_npe, sbuf );
strcat( buf, sbuf );
strcat( buf, " " );
li_code( (double) dwd, dwd_low, dwd_high, (int)dwd_npe, sbuf );
strcat( buf, sbuf );
strcat( buf, " " );
strcat( buf, " " );
strcat( buf, (prec_tod > prec_thr) ? "1" : "0" );
strcat( buf, (prec_tom > prec_thr) ? "1" : "0" );
strcat( buf, (prec_nxt > prec_thr) ? "1" : "0" );
strcat( buf, NEW_LINE_STR );
} else {
denom = bp_high - bp_low;
if (denom >= 0.0001 ) nbp = ( bp - bp_low ) / denom;
else nbp = 0.0;
denom = dbp_high - dbp_low;
if (denom >= 0.0001 ) ndbp = ( dbp - dbp_low ) / denom;
else ndbp = 0.0;
denom = wd_high - wd_low;
if (denom >= 0.0001 ) nwd = ( wd - wd_low ) / denom;
else nwd = 0.0;
denom = dwd_high - dwd_low;
if (denom >= 0.0001 ) ndwd = ( dwd - dwd_low ) / denom;
else ndwd = 0.0;
sprintf( buf, "%s %6.3f %6.3f %6.3f %6.3f %6.3f %6.3f %6.3f%s",
date, nbp, ndbp, nwd, ndwd, prec_tod, prec_tom, prec_nxt, NEW_LINE_STR );
}
}
#ifdef ANSI_HEADER
void li_code( double val, double low, double high, int npe, char *sbuf )
#else
void li_code( val, low, high, npe, sbuf )
double val, low, high;
int npe;
char *sbuf;
#endif
{
float increm;
int wx;
int pos = 0;
strcpy( sbuf, "" );
if ( npe > 0 ) {
increm = ( high - low) / (float) npe;
if ( increm > 0.0001) pos = (int) ( (val - low) / increm);
if ( pos < 0 ) pos = 0;
if ( pos >= npe ) pos = npe - 1;
for ( wx = 0; wx < npe; wx++ )
strcat( sbuf, (wx == pos) ? "1" : "0" );
}
}
void decode( )
{
char wc; /* work character */
float *pio; /* pointer to IODATA */
int wx;
char *sp;
if ( nw_type == ADALINE ) {
pio = IODATA;
sp = fbuf[0];
sscanf( sp, "%s", date );
sp += strlen( date );
for ( wx = 0; wx < ninp; wx++ ) {
do sscanf( sp++, "%1c", &wc );
while ( wc == ' ' ) ;
if ( wc == '0' ) *pio++ = -1.0;
else *pio++ = 1.0;
}
do sscanf( sp++, "%1c", &wc );
while ( wc == ' ' ) ;
if ( wc == '0' ) prec_tod = -1.0;
else prec_tod = 1.0;
do sscanf( sp++, "%1c", &wc );
while ( wc == ' ' ) ;
if ( wc == '0' ) prec_tom = -1.0;
else prec_tom = 1.0;
do sscanf( sp++, "%1c", &wc );
while ( wc == ' ' ) ;
if ( wc == '0' ) prec_nxt = -1.0;
else prec_nxt = 1.0;
} else {
sscanf( fbuf[0], "%s %f %f %f %f %f %f %f",
date, &IODATA[0], &IODATA[1], &IODATA[2], &IODATA[3],
&prec_tod, &prec_tom, &prec_nxt );
}
}
void disp_rwdw( ) /* Display recall window */
{
ug_window( 1, gm_intcolor, rstrtx, rstrty, rstrtx + rendx, rstrty + rendy );
ug_box( 1, gm_outcolor, 0, 0, rendy, rendx, rendy, 0 );
ug_line( 1, gm_outcolor, 0, rdata, 0, rdata, rendy , 0 );
ug_line( 1, gm_outcolor, 0, 0, dateline, rendx, dateline , 0 );
ug_line( 1, gm_outcolor, 0, 0, actline, rendx, actline , 0 );
ug_puts( 1, gm_txtcolor, 0, X_MARGIN, rtod_y, "Today:", 0 );
ug_puts( 1, gm_txtcolor, 0, X_MARGIN, ract_y, "Actual:", 0 );
ug_puts( 1, gm_txtcolor, 0, X_MARGIN, rtom_y, "Tomorrow:", 0 );
ug_puts( 1, gm_txtcolor, 0, X_MARGIN, rnxt_y, "Next Day:", 0 );
}
void disp_forecast( )
{
int size, x0;
x0 = rdata + 2 + curr_pos * ( chry + 2 );
size = IODATA[0] * chry;
if ( size < 1 ) size = 1;
if ( size > chry ) size = chry;
ug_boxf( 1, gm_txtcolor, 0, x0, rtod_y, x0 + size - 1, rtod_y + size - 1 );
size = prec_tod * chry;
if ( size < 1 ) size = 1;
if ( size > chry ) size = chry;
ug_boxf( 1, gm_txtcolor, 0, x0, ract_y, x0 + size - 1, ract_y + size - 1 );
ug_puts( 1, gm_txtcolor, 0, x0 + chry + 1, dateline + 2, date, 1 );
x0 += chry+2;
size = IODATA[1] * chry;
if ( size < 1 ) size = 1;
if ( size > chry ) size = chry;
ug_boxf( 1, gm_txtcolor, 0, x0, rtom_y, x0 + size - 1, rtom_y + size - 1 );
x0 += chry+2;
size = IODATA[2] * ( chry );
if ( size < 1 ) size = 1;
if ( size > chry ) size = chry;
ug_boxf( 1, gm_txtcolor, 0, x0, rnxt_y, x0 + size - 1, rnxt_y + size - 1 );
}
/************************************************************************
*
* UsrIO - user I/O routine to handle requests from NWORKS
*
************************************************************************
*/
static int AbortFlag = 0;
static int InitFlag = 0;
int UsrIO() /* handle NWORKS requests */
{
int wx; /* work indices */
int key, xp, yp, button; /* mouse interface */
char *sp; /* string pointer */
long total_npe; /* Total # PEs */
int oldwd;
float oldbp;
char sbuf[100]; /* string buffer */
IORTNCDE = 0; /* good return for data */
if ( InitFlag == 0 ) {
/* Read network parameters */
ug_rdnetinf( &nlayp, &ninp, &noutp, <ype, &csp, &netnp );
/* strcpy( file_name, netnp ); */
strcpy( file_name, "june.dat" );
/* Get graphics parameters */
ug_gparms( &xsize, &ysize, &ncolor, &chrx, &chry );
if ( ncolor < 8 ) {
gm_intcolor = 1;
gm_txtcolor = 0;
gm_outcolor = 0;
} else {
gm_intcolor = 7;
gm_txtcolor = 4;
gm_outcolor = 0;
}
ract_y = Y_MARGIN;
actline = ract_y + chry + 2;
rnxt_y = ract_y + Y_MARGIN + chry + 1;
rtom_y = rnxt_y + Y_MARGIN + chry;
rtod_y = rtom_y + Y_MARGIN + chry;
dateline = rtod_y + chry + Y_MARGIN + 1;
rendy = dateline + 8 * chrx + 2 * Y_MARGIN + 1;
rdata = 9 * chrx + 2 * X_MARGIN + 2;
rendx = rdata + 2 * X_MARGIN + ( chry + 2 ) * NUM_DISP + 1;
rstrtx = ( xsize - rendx ) / 2;
rstrty = ( ysize - rendy ) / 2;
InitFlag = 1;
}
switch( IOREQCDE ) {
case RQ_ATTENTION:
/* This is invoked at the request of the user from the
execute menu. It allows parameters to be changed or
altered. Any graphics or other interactions are allowable
as usual for the other options.
*/
if ( ifp != (FILE *) NULL ) fclose( ifp );
if ( fp != (FILE *) NULL ) fclose( fp );
ug_rdnetinf( &nlayp, &ninp, &noutp, <ype, &csp, &netnp );
if ( strcmpl( csp, "Adaline") == 0 ) nw_type = ADALINE;
else nw_type = OTHER;
PutStr(
"This will process your weather file to a form acceptable by the network\n");
/* Read weather file */
PutStr("Enter name of weather data file:");
sp = GetStr( );
if ( ( fp = fopen( sp, "r" ) ) == NULL) {
sprintf( sbuf, "Cannot find file <%s>\n", sp );
PutStr( sbuf );
goto bad_return;
}
PutStr("Enter name of transformed file:");
sp = GetStr( );
#if !defined(MAC) && !defined(VMS)
unlink( sp ); /* delete if it already exists */
#endif
if ( ( ifp = fopen( sp, "w" ) ) == NULL) {
sprintf( sbuf, "Cannot open file <%s>\n", sp );
PutStr( sbuf );
goto bad_return;
}
strcpy( file_name, sp );
/****************************************/
/* Read in weather parameters from file */
/****************************************/
if ( fgets( fbuf[0], MAX_STR, fp) == 0 ) {
PutStr("Could not read precipitation threshold; i/o aborted\n");
goto bad_return;
}
sscanf( fbuf[0], "%f", &prec_thr );
if ( fgets( fbuf[0], MAX_STR, fp) == 0 ) {
PutStr(
"Could not read barometric pressure parameters; i/o aborted\n");
goto bad_return;
}
sscanf( fbuf[0], "%f %f %ld",
&bp_low, &bp_high, &bp_npe );
if ( fgets( fbuf[0], MAX_STR, fp) == 0 ) {
PutStr(
"Could not read delta barometric pressure parameters; i/o aborted\n");
goto bad_return;
}
sscanf( fbuf[0], "%f %f %ld",
&dbp_low, &dbp_high, &dbp_npe );
if ( fgets( fbuf[0], MAX_STR, fp) == 0 ) {
PutStr("Could not read weather direction parameters; i/o aborted\n");
goto bad_return;
}
sscanf( fbuf[0], "%f %f %ld",
&wd_low, &wd_high, &wd_npe );
if ( fgets( fbuf[0], MAX_STR, fp) == 0 ) {
PutStr(
"Could not read delta weather direction parameters; i/o aborted\n");
goto bad_return;
}
sscanf( fbuf[0], "%f %f %ld",
&dwd_low, &dwd_high, &dwd_npe );
if ( nw_type == ADALINE )
total_npe = bp_npe + dbp_npe + wd_npe + dwd_npe;
else total_npe = 4;
sprintf(fbuf[0], "%ld %f ! Number PEs, precipitation threshold%s",
total_npe, prec_thr,NEW_LINE_STR );
fputs( fbuf[0], ifp );
/****************************************************************/
/* Read in weather data from file, convert, write to input file */
/****************************************************************/
tod_buff = 0;
tom_buff = 1;
nxt_buff = 2;
/* Read in first three lines of data */
if ( fgets( fbuf[tod_buff], MAX_STR, fp ) == 0 ) {
PutStr(" Insufficient data! ");
goto bad_return;
}
if ( fgets( fbuf[tom_buff], MAX_STR, fp ) == 0 ) {
PutStr(" Insufficient data! ");
goto bad_return;
}
if ( fgets( fbuf[nxt_buff], MAX_STR, fp ) == 0 ) {
PutStr(" Insufficient data! ");
goto bad_return;
}
sscanf( fbuf[nxt_buff], "%s %f %ld %f", date, &bp, &wd, &prec_nxt );
sscanf( fbuf[tom_buff], "%s %f %ld %f", date, &bp, &wd, &prec_tom );
sscanf( fbuf[tod_buff], "%s %f %ld %f", date, &bp, &wd, &prec_tod );
dbp = 0.0;
dwd = 0;
encode( fbuf[tod_buff] );
fputs( fbuf[tod_buff], ifp );
oldbp = bp;
oldwd = wd;
while ( fgets(fbuf[tod_buff],MAX_STR,fp) != 0 ) {
wx = tod_buff; /* rotate buffer indices */
tod_buff = tom_buff;
tom_buff = nxt_buff;
nxt_buff = wx;
sscanf( fbuf[nxt_buff], "%s %f %ld %f", date, &bp, &wd, &prec_nxt );
sscanf( fbuf[tom_buff], "%s %f %ld %f", date, &bp, &wd, &prec_tom );
sscanf( fbuf[tod_buff], "%s %f %ld %f", date, &bp, &wd, &prec_tod );
dbp = bp - oldbp;
dwd = wd - oldwd;
if ( dwd > 180 ) dwd -= 360;
else if ( dwd <= -180 ) dwd += 360;
encode( fbuf[tod_buff] );
fputs( fbuf[tod_buff], ifp );
oldbp = bp;
oldwd = wd;
}
fclose( fp );
fclose( ifp );
PutStr( "Data successfully transformed\n" );
return(0);
bad_return:
IORTNCDE = -1;
if ( ifp != (FILE *) NULL ) fclose( ifp );
if ( fp != (FILE *) NULL ) fclose( fp );
break;
case RQ_LSTART: /* starting learn */
/* This tells the user that the program is about to start
learning. It is called once for a LEARN ALL, LEARN ONE,
LEARN N, or LEARN START
*/
case RQ_RSTART: /* starting recall */
/* This tells the user that the program is about to start
a recall. It is called once for a RECALL ALL, RECALL ONE,
RECALL N, or RECALL START.
*/
AbortFlag = 0;
/* Read network parameters */
ug_rdnetinf( &nlayp, &ninp, &noutp, <ype, &csp, &netnp );
if ( strcmpl( csp, "Adaline") == 0 ) nw_type = ADALINE;
else nw_type = OTHER;
/* Read weather file */
if ( ifp != (FILE *) NULL ) fclose( ifp );
sprintf( sbuf, "Enter name of input file ( default: %s ):", file_name );
PutStr( sbuf );
sp = GetStr();
PutStr("\n");
if ( strcmp( sp, "" ) != 0 ) strcpy( file_name, sp );
if ( ( ifp = fopen( file_name, "r" ) ) == NULL ) {
sprintf( sbuf, "Cannot find file <%s>\n", file_name );
PutStr( sbuf );
goto abort;
}
/* Read in header */
if ( fgets( fbuf[0], MAX_STR, ifp ) == 0 ) {
PutStr("Cannot read header; i/o aborted\n");
goto abort;
}
sscanf( fbuf[0], "%ld %f", &total_npe, &prec_thr );
if ( total_npe != ninp ) {
PutStr( "Mismatch between network and input file; i/o aborted\n");
sprintf( sbuf,
"Number of network inputs = %ld, number of file inputs = %ld\n",
(long)ninp, total_npe );
PutStr( sbuf );
goto abort;
}
num_readings = 0;
if ( IOREQCDE == RQ_RSTART ) {
disp_rwdw( );
curr_pos = 0;
no_more_data = 0;
tod_correct = tom_correct = nxt_correct = 0.0;
}
else {
start_pos = ftell( ifp ); /* start position for file data */
tod_mse = tom_mse = nxt_mse = 0.0; /* Initialize mean square errors */
}
return(0);
abort:
IORTNCDE = -1;
AbortFlag = 1;
if ( ifp != (FILE *) NULL ) fclose( ifp );
break;
case RQ_LEARNIN: /* read training input */
/* IODATA points to an empty array of IOCOUNT elements. The
values placed in this array by the user will become the
inputs to the network for training purposes.
*/
if ( AbortFlag ) {
IORTNCDE = -1;
return(0);
}
num_readings++;
if ( fgets( fbuf[0], MAX_STR, ifp ) == 0 ) {
fseek( ifp, start_pos, 0 ); /* If at end return to start */
fgets( fbuf[0], MAX_STR, ifp );
sprintf ( sbuf,
"Mean square error. today: %5.3f, tomorrow: %5.3f, next day: %5.3f\n",
sqrt(tod_mse) / num_readings,
sqrt(tom_mse) / num_readings,
sqrt(nxt_mse) / num_readings );
PutStr( sbuf );
tod_mse = tom_mse = nxt_mse = 0.0;
num_readings = 0;
}
decode( );
break;
case RQ_READ: /* read test data */
/* IODATA points to an empty array of IOCOUNT values. The
user must fill in these values. The elements of the
array will become the "sum" of the inputs to the input
layer of processing elements.
*/
/* Read next line of data from file */
if ( AbortFlag ) {
IORTNCDE = -1;
return;
}
if ( fgets( fbuf[0], MAX_STR, ifp ) != 0 ) {
decode( );
num_readings++;
}
else no_more_data = 1;
break;
case RQ_LEARNOUT: /* read desired output */
/* IODATA points to an empty array of IOCOUNT values. The
elements of the array will become the desired outputs for
training purposes. These desired outputs correspond to
the most recent "RQ_LEARNIN" request.
*/
case RQ_RCLTST: /* read desired output during recall test */
/* IODATA points to an empty array of IOCOUNT values. The
elements of the array will become the desired outputs for
recall purposes. This request is only made during a
Execute Network/Recall Test.
*/
IODATA[0] = prec_tod;
IODATA[1] = prec_tom;
IODATA[2] = prec_nxt;
break;
case RQ_WRSTEP: /* write interim results */
/* each recall cycle for the Hopfield and BAM control strategies,
the intermediate output is made available to userio to test
for convergence or other desired states. This option is
not used for other control strategies.
*/
if (AbortFlag) {
IORTNCDE = -1;
return;
}
break;
case RQ_LEARNRSLT:
/* IODATA points to an array of IOCOUNT values. These are the
output of the network caused by the inputs from RQ_LEARNIN.
*/
if (AbortFlag) {
IORTNCDE = -1;
return;
}
tod_mse += ( IODATA[0] - prec_tod ) * ( IODATA[0] - prec_tod );
tom_mse += ( IODATA[1] - prec_tom ) * ( IODATA[1] - prec_tom );
nxt_mse += ( IODATA[2] - prec_nxt ) * ( IODATA[2] - prec_nxt );
break;
case RQ_WRITE: /* write out results */
/* IODATA points to an array of IOCOUNT "float" type values.
The values are the outputs of the top-most layer of the
network.
*/
if (AbortFlag) {
IORTNCDE = -1;
return;
}
if ( no_more_data ) {
PutStr( "No more data; press mouse button to quit.\n" );
sprintf( sbuf,
"Percentage correct: today: %5.1f, tomorrow: %5.1f, next day: %5.1f\n",
( tod_correct / num_readings ) * 100.0,
( tom_correct / num_readings ) * 100.0,
( nxt_correct / num_readings ) * 100.0 );
PutStr( sbuf );
for ( ; ; ) {
ug_mouse( &key, &xp, &yp, &button );
if ( button == MBUT_RIGHT || button == MBUT_LEFT ) {
IORTNCDE = -1;
goto end_write;
}
}
} else {
if ( (IODATA[0] >= prec_thr && prec_tod >= prec_thr) ||
(IODATA[0] < prec_thr && prec_tod < prec_thr) )
tod_correct += 1.0;
if ( (IODATA[1] >= prec_thr && prec_tom >= prec_thr) ||
(IODATA[1] < prec_thr && prec_tom < prec_thr) )
tom_correct += 1.0;
if ( (IODATA[2] >= prec_thr && prec_nxt >= prec_thr) ||
(IODATA[2] < prec_thr && prec_nxt < prec_thr) )
nxt_correct += 1.0;
disp_forecast( );
if ( ++curr_pos >= NUM_DISP ) {
curr_pos = 0;
#ifdef MAC
PutStr(
"Press mouse button to continue; clover mouse button to abort.\n" );
#else
PutStr(
"Press right button to abort, left button to continue.\n" );
#endif
for ( ; ; ) {
ug_mouse( &key, &xp, &yp, &button );
if ( button == MBUT_RIGHT ) {
IORTNCDE = -1;
goto end_write;
}
if ( button == MBUT_LEFT ) {
disp_rwdw( ); /* Redisplay recall window */
goto end_write;
}
}
}
}
end_write:
break;
case RQ_TERM: /* terminate interface */
/* close any files which may be open. Deallocate any memory
which was allocated. (This is VERY VERY important. If
allocated memory is NOT released, dos memory will become
fragmented and it will become necessary to reboot.
*/
PutStr( "bye bye\n" );
if ( ifp != (FILE *) NULL ) fclose( ifp );
if ( fp != (FILE *) NULL ) fclose( fp );
break;
}
return;
}